/* ----------------------------------------------------------------------
*
* Copyright (C) 2025 XiaoFei. All rights reserved.
*
* @file:		XiaoZhi_OLED.c
* @author:		XiaoFei
* @Date:     	16-January-2025
* @Revision: 	V1
* @Project: 	XiaoFei BSP Library
*
* -------------------------------------------------------------------- */

#include "stm32f10x.h"
#include "XiaoFei_Delay.h"
#include "XiaoZhi_OLED.h"
#include "XiaoFei_Font.h"
#include "stdio.h"
#include "stdarg.h"

/* 
* @function: 	OLED_SendByte
* @parameter:	[in] Byte				    The Byte will be write.
*/
static void OLED_SendByte(unsigned char Byte)
{
	#ifdef OLED_UseI2C
		for(unsigned int i=0;i<8;i++)
		{
			OLED_SDA(!!(Byte&(0x80>>i)));
			OLED_SCL(1);
			OLED_SCL(0);
		}
		OLED_SCL(1);
		OLED_SCL(0);
	#endif
	#ifdef OLED_UseSPI
		for(unsigned char i=0;i<8;i++)
		{
			OLED_SCL(0);
			OLED_SDA(!!(Byte&0x80));
			OLED_SCL(1);
			Byte<<=1;
		}
	#endif
}

/* 
* @function: 	OLED_WriteCommand
* @parameter:	[in] Command				 The command will be write.
*/
static void OLED_WriteCommand(unsigned char Command)
{
	#ifdef OLED_UseI2C
		OLED_SDA(1);
		OLED_SCL(1);
		OLED_SDA(0);
		OLED_SCL(0);
		OLED_SendByte(OLED_Device_ID);
		OLED_SendByte(OLED_WrCommand_Code);
		OLED_SendByte(Command);
		OLED_SDA(0);
		OLED_SCL(1);
		OLED_SDA(1);
	#endif
	#ifdef OLED_UseSPI
		OLED_DC(0);
		OLED_SendByte(Command);
		OLED_DC(1);
	#endif
}

/* 
* @function: 	OLED_Init
*/
void OLED_Init(void)
{
	#ifdef OLED_UseI2C
    	XiaoFei_Delay_ms(100);
		RCC_APB2PeriphClockCmd(OLED_RCC_SDA,ENABLE);
		GPIO_InitTypeDef GPIO_InitStructure;
		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
		GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Pin=OLED_PIN_SDA;
		GPIO_Init(OLED_GPIO_SDA,&GPIO_InitStructure);
		RCC_APB2PeriphClockCmd(OLED_RCC_SCL,ENABLE);
		GPIO_InitStructure.GPIO_Pin=OLED_PIN_SCL;
		GPIO_Init(OLED_GPIO_SCL,&GPIO_InitStructure);
		OLED_SCL(1);
	    OLED_SDA(1);
	#endif
	#ifdef OLED_UseSPI
		RCC_APB2PeriphClockCmd(OLED_RCC_SDA,ENABLE);
		GPIO_InitTypeDef GPIO_InitStructure;
		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
		GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Pin=OLED_PIN_SDA;
		GPIO_Init(OLED_GPIO_SDA,&GPIO_InitStructure);
		RCC_APB2PeriphClockCmd(OLED_RCC_SCL,ENABLE);
		GPIO_InitStructure.GPIO_Pin=OLED_PIN_SCL;
		GPIO_Init(OLED_GPIO_SCL,&GPIO_InitStructure);
		RCC_APB2PeriphClockCmd(OLED_RCC_RES,ENABLE);
		GPIO_InitStructure.GPIO_Pin=OLED_PIN_RES;
		GPIO_Init(OLED_GPIO_RES,&GPIO_InitStructure);
		RCC_APB2PeriphClockCmd(OLED_RCC_DC,ENABLE);
		GPIO_InitStructure.GPIO_Pin=OLED_PIN_DC;
		GPIO_Init(OLED_GPIO_DC,&GPIO_InitStructure);
		OLED_RES(0);
		XiaoFei_Delay_ms(200);
		OLED_RES(1);
		XiaoFei_Delay_ms(200);
	#endif
	OLED_WriteCommand(OLED_Display_Off);
	OLED_WriteCommand(OLED_SetFreq_High);
	OLED_WriteCommand(OLED_SetFreq_Low);
	OLED_WriteCommand(OLED_SetMulRat_High);
	OLED_WriteCommand(OLED_SetMulRat_Low);
	OLED_WriteCommand(OLED_SetOffset_High);
	OLED_WriteCommand(OLED_SetOffset_Low);
	OLED_WriteCommand(OLED_Set_StartLine);
	OLED_WriteCommand(OLED_X_Normal);
	OLED_WriteCommand(OLED_Y_Normal);
	OLED_WriteCommand(OLED_OutScanDir_High);
	OLED_WriteCommand(OLED_OutScanDir_Low);
	OLED_WriteCommand(OLED_ContrastCon_High);
	OLED_WriteCommand(OLED_ContrastCon_Low);
	OLED_WriteCommand(OLED_PreCharge_High);
	OLED_WriteCommand(OLED_PreCharge_Low);
	OLED_WriteCommand(OLED_VCOMHDeLev_High);
	OLED_WriteCommand(OLED_VCOMHDeLev_Low);
	OLED_WriteCommand(OLED_SetShow_On);
	OLED_WriteCommand(OLED_SetShow_Normal);
	OLED_WriteCommand(OLED_SetCharPump_High);
	OLED_WriteCommand(OLED_SetCharPump_Low);
	OLED_WriteCommand(OLED_Display_On);
	OLED_Clear();           
}                         

/* 
* @function: 	OLED_WriteData
* @parameter:	[in] Data					 The data will be write.
*/
static void OLED_WriteData(unsigned char Data)
{
	#ifdef OLED_UseI2C
		OLED_SDA(1);
		OLED_SCL(1);
		OLED_SDA(0);
		OLED_SCL(0);
		OLED_SendByte(OLED_Device_ID);
		OLED_SendByte(OLED_WrData_Code);
		OLED_SendByte(Data);
		OLED_SDA(0);
		OLED_SCL(1);
		OLED_SDA(1);
	#endif
    #ifdef OLED_UseSPI
		OLED_DC(1);
		OLED_SendByte(Data);
		OLED_DC(1);
	#endif
}

/* 
* @function: 	OLED_SetCursor
* @parameter:	[in] Cursor					 Handle to the cursor position.
*/
static void OLED_SetCursor(Cursor_TypeDef* Point)
{
	OLED_WriteCommand(OLED_CursorY|Point->Line);
	OLED_WriteCommand(OLED_CursorX_High|((Point->Column&0xF0)>>4));
	OLED_WriteCommand(OLED_CursorX_Low|(Point->Column&0x0F));
}

/* 
* @function: 	OLED_Clear
*/
void OLED_Clear(void)
{  
	Cursor_TypeDef Point;
	Point.Column=0;
	for (unsigned char j=0;j<8;j++)
	{
		Point.Line=j;
		OLED_SetCursor(&Point);
		for(unsigned char i=0;i<128;i++)
			OLED_WriteData(0x00);
	}
}

/* 
* @function: 	OLED_ShowChar
* @parameter:	[in] Cursor					 Handle to the cursor position.
* @parameter:	[in] show					 The character to be displayed.
*/
void OLED_ShowChar(Cursor_TypeDef* Cursor, char show)
{
	Cursor_TypeDef Point1,Point2;
	Point1.Line=(Cursor->Line-1)*2;
	Point1.Column=(Cursor->Column-1)*8;
	Point2.Line=(Cursor->Line-1)*2+1;
	Point2.Column=(Cursor->Column-1)*8;
	OLED_SetCursor(&Point1);
	for(unsigned int i=0;i<8;i++)
		OLED_WriteData(XiaoFei_Font16[show-0x20][i]);
	OLED_SetCursor(&Point2);
	for(unsigned int i=0;i<8;i++)
		OLED_WriteData(XiaoFei_Font16[show-0x20][i+8]);
}

/* 
* @function: 	OLED_ShowString
* @parameter:	[in] Cursor					 Handle to the cursor position.
* @parameter:	[in] String					 The String to be displayed.
*/
void OLED_ShowString(Cursor_TypeDef* Cursor, char* String)
{
	Cursor_TypeDef Cursor1;
	Cursor1.Line=Cursor->Line;
	for(unsigned char i=0;String[i]!=0x00;i++)
	{
		Cursor1.Column=Cursor->Column+i;
		OLED_ShowChar(&Cursor1,String[i]);
	}
}

/* 
* @function: 	OLED_ShowChinese
* @parameter:	[in] Cursor					 Handle to the cursor position.
* @parameter:	[in] Chinese				 Handle of the Chinese character to be displayed.
*/
void OLED_ShowChinese(Cursor_TypeDef* Cursor, unsigned int Chinese)
{
	Cursor_TypeDef Point1,Point2;
	Point1.Line=(Cursor->Line-1)*2;
	Point1.Column=(Cursor->Column-1)*16;
	Point2.Line=(Cursor->Line-1)*2+1;
	Point2.Column=(Cursor->Column-1)*16;
	OLED_SetCursor(&Point1);
	for(unsigned int i=0;i<16;i++)
		OLED_WriteData(XiaoFei_Chinese16[Chinese][i]);
	OLED_SetCursor(&Point2);
	for(unsigned int i=0;i<16;i++)
		OLED_WriteData(XiaoFei_Chinese16[Chinese][i+16]);
}

/* 
* @function: 	OLED_ShowChineseString
* @parameter:	[in] Cursor					 Handle to the cursor position.
* @parameter:	[in] Chinese				 Handle of the Chinese character to be displayed.
* @parameter:	[in] num				     The num of the Chinese character to be displayed.
*/
void OLED_ShowChineseString(Cursor_TypeDef* Cursor, unsigned int Chinese, unsigned int num)
{
	for(unsigned int i=0;i<num;i++)
		OLED_ShowChinese(&((Cursor_TypeDef){Cursor->Line,Cursor->Column+i}),i);
}

/* 
* @function: 	OLED_Printf
* @parameter:	[in] Cursor					 Handle to the cursor position.
* @parameter:	[in] format					 The parameter will be send in OLED_Printf.
*/
void OLED_Printf(Cursor_TypeDef* Cursor, char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	OLED_ShowString(Cursor,String);
}



